package edu.ncsu.csc.ip.routing.dv;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;

/**
 * Class <code>distance_vector</code>
 * 
 * distance_vector to comply with project description
 * 
 * @author Moin Ayazifar <mayazif@ncsu.edu>
 * @author Steven Elliott <sdelliot@ncsu.edu>
 * 
 */

public class RunTask2 {

	HashMap<String, RouterLocal> nodesMap = new HashMap<String, RouterLocal>();
	public static final boolean DIRECTED_GRAPH = false;

	public static Comparator<String> NodeNameComparator = new Comparator<String>() {
		public int compare(String node1, String node2) {
			// ascending order
			return Integer.valueOf(node1).compareTo(Integer.valueOf(node2));
		}
	};

	public static Comparator<RouterLocal> NodeNameRouterComparator = new Comparator<RouterLocal>() {
		public int compare(RouterLocal r1, RouterLocal r2) {
			// ascending order
			return Integer.valueOf(r1.localNode.getName()).compareTo(
					Integer.valueOf(r2.localNode.getName()));
		}
	};

	public static void main(String[] args) throws Exception {

		RunTask2 dv = new RunTask2();
		// Initial Load
		dv.loadGraph(args[0]);
		String[] nodeNames = dv.nodesMap.keySet().toArray(
				new String[dv.nodesMap.size()]);

		Arrays.sort(nodeNames, NodeNameComparator);
		new File("./results").mkdir();

		for (String nodeName : nodeNames) {
			dv.loadGraph(args[0]);

			RouterLocal[] routerArray = dv.nodesMap.values().toArray(
					new RouterLocal[dv.nodesMap.size()]);
			Arrays.sort(routerArray, NodeNameRouterComparator);

			dv.nodesMap.get(nodeName).initialize();
			dv.nodesMap.get(nodeName).start();
			for (RouterLocal r : routerArray) {
				if (r != dv.nodesMap.get(nodeName))
					r.initialize();
			}

			for (RouterLocal r : routerArray) {
				if (r != dv.nodesMap.get(nodeName))
					r.start();
			}

			int wait_time = 5000;
			System.out.println(" Waiting for the network to converge.");
			Thread.sleep(wait_time);

			// for (RouterLocal r : dv.nodesMap.values())
			// r.localNode.printDv();

			String fileName = "./results/Task2_" + nodeName + "_results.csv";
			File file = new File(fileName);
			PrintWriter printWrite = new PrintWriter(
					new FileWriter(file, false));
			printWrite
					.println("Node("
							+ nodeName
							+ ") , Iteration, Cumulative Iteration, Sent, Cumulative Sent, Received, Cumulative Received");

			int totalIt = 0;
			int totalSent = 0;
			int totalReceived = 0;
			for (RouterLocal r : routerArray) {
				totalIt += r.getIteration();
				totalSent += r.getUpdatesSent();
				totalReceived += r.getUpdateReceived();
				printWrite.println(r.localNode + "," + r.getIteration() + ","
						+ totalIt + "," + r.getUpdatesSent() + "," + totalSent
						+ "," + r.getUpdateReceived() + "," + totalReceived);
			}
			printWrite.close();
			System.out.println("Finished writing " + fileName);
		}
	}

	public void loadGraph(String fileName) throws IOException {
		File file;
		BufferedReader fileReader;

		// clear the map only one of the following is needed
		nodesMap = new HashMap<String, RouterLocal>();
		// nodesMap.clear();

		file = new File(fileName);
		fileReader = new BufferedReader(new FileReader(file));
		String line;

		int nodeCount = Integer.parseInt(fileReader.readLine());
		while ((line = fileReader.readLine()) != null) {

			String[] params = line.split(" ");
			double weight = Double.parseDouble(params[2]);
			if (!nodesMap.containsKey(params[0]))
				nodesMap.put(params[0], new RouterLocal(new Node(params[0])));
			if (!nodesMap.containsKey(params[1]))
				nodesMap.put(params[1], new RouterLocal(new Node(params[1])));

			nodesMap.get(params[0]).localNode.neighborsMap.put(
					nodesMap.get(params[1]).localNode,
					new RouteEntity(nodesMap.get(params[1]).localNode, weight));

			if (!DIRECTED_GRAPH)
				nodesMap.get(params[1]).localNode.neighborsMap.put(nodesMap
						.get(params[0]).localNode,
						new RouteEntity(nodesMap.get(params[0]).localNode,
								weight));
		}
		System.out.println(" Graph Loaded");
		fileReader.close();
		if (nodeCount != nodesMap.size())
			throw new RuntimeException(
					"Number of nodes doesn't match the first line of the input");

	}

}
